<html>
<head>
    <meta charset="UTF-8">
    <title>1.1-Var声明与变量提升</title>
</head>
<body>
<!--
使用 var 声明的变量，会提升到当前作用域的最顶部或者是全局作用域，叫做变量提升 Hoisting 。
变量没声明 和 变量声明没赋值 是不一样的概念，使用 var 声明的变量的如果值是 undefined ，其实是声明了但没赋值，如果使用没有声明的变量会报错。
let 声明
const 声明，const 声明的变量不能被重新赋值，但是如果 const 声明的值是对象，那么这个对象是可以修改了。
-->
</body>
<script>

    function basic() {
        const person = {
            name: "Nicholas"
        };
        // 正常
        person.name = "Greg";
        // 扩展 person 也是可以的
        person.age = 18;
        // 抛出错误
        /*person = {
            name: "Greg"
        };*/
        // const 阻止的是绑定的修改，而不是绑定值的修改。 注:这个跟java的static修饰对象和修饰变量的一个意思。

        /*****************************************
         *  var 的问题
         * ****************************************/
        var funcs = [];

        for (var i = 0; i < 10; i++) {
            funcs.push(function () {
                console.log(i);
            });// 数组里边存放的元素为回调函数.并不会立即执行,需要客户端调用
        }

        // 遍历出数组中的每个元素(函数)
        funcs.forEach(function (func) {
            func();     // 输出 "10" 共10次
        });

        /****************************
         * var 会覆盖 window 里的定义
         * **************************/
            // 在浏览器中运行
        var RegExp = "Hello!";
        console.log(window.RegExp);     // "Hello!"

        var ncz = "Hi!";
        console.log(window.ncz);        // "Hi!"
    }

    //////////////////////////////////////////  Var 声明与变量提升 DEMO  START  /////////////////////////////////////////////
    // var Declarations And Hoisting
    // 使用 var 关键字声明的变量，不论在何处都会被视作在函数级作用域内顶部的位置发生（如果不包含在函数内则为全局作用域内）。
    function getValue(condition) {

        if (condition) {
            var value = "blue";
            console.log("1-condistion:" + condition, value);
            // 其它代码


            return value;
        } else {

            // value 可以被访问到，其值为 undefined  变量是有声明的，只是没有赋值，所以为undefined
            console.log("2-condistion:" + condition, value);

            return null;
        }

        // 这里也可以访问到 value，值仍为 undefined
        console.log("3-condistion:" + condition, value);
    }

    console.group('------------Test: Var 声明与变量提升 ------------')
    getValue(true);
    getValue(false);
    getValue()
    console.groupEnd();
    // 如果你不太熟悉 JavaScript，或许会认为只有 condition 为 true 时变量 value 才会被创建。实际上，value 总是会被创建。JavaScript 引擎在幕后对 getValue 函数做了调整，可以视为：
    /*
    * function getValue(condition) {

            var value;

            if (condition) {
                value = "blue";

                // 其它代码

                return value;
            } else {

                return null;
            }
        }
        变量的声明被提升至顶部，但是初始化的位置并没有改变，这意味着在 else 从句内部也能访问 value 变量，但如果真的这么做的话，value 的值会是 undefined，因为它并没有被初始化或赋值。

        刚开始接触 JavaScript 的开发者总是要花一段时间来习惯变量提升，对该独特概念的陌生也会造成 bug。因此 ECMAScript 6 引入了块级作用域的概念使得变量的生命周期变得更加可控。

    * */
    //////////////////////////////////////////  Var 声明与变量提升 DEMO  END  /////////////////////////////////////////////




</script>
</html>